/*
 Rilego - An easy Images 2 E-Book converter.
Copyright (C) 2011  Federico Improta (Kirys)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/

package it.kirys.rilego.engine.processors;
import it.kirys.rilego.engine.loaders.imagesources.ImageType;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 *
 * @author Federico Improta
 */
public class ImageInfo {
    //constats
    static final int BUFFSIZE=10240*5;
 

    private ImageType type=null;
    private int width=-1;
    private int height=-1;
    
    public int getWidth(){
        return width;
    }
    
    public int getHeight(){
        return height;
    }
    
    public boolean isKnown(){
        return type!=null;
    }
    
    protected void assignImage(BufferedInputStream stream,String Filename){
        type=null;
        byte[] buff=null;
        width=-1;
        height=-1;
        
        if (stream==null){
            buff=readBlock(Filename);
        }else {
            buff=readBlock(stream);
        }
        
		  type=ImageType.getFromFileName(Filename);
    }
    
    private byte[] readBlock(BufferedInputStream stream){

        DataInputStream dis = null;
        byte[] buff=new byte[BUFFSIZE];
        try {

            dis = new DataInputStream(stream);

            // dis.available() returns 0 if the file does not have more lines.
            dis.read(buff);

            // dispose all the resources after using them.
            dis.close();
            return buff;
    } catch (IOException e) {
      e.printStackTrace();
      return null;
    }        
    }    
    
    private byte[] readBlock(String Filename){
        FileInputStream fis = null;
        BufferedInputStream bis = null;

        byte[] buff=null;
        try {
            fis = new FileInputStream(Filename);

            // Here BufferedInputStream is added for fast reading.
            bis = new BufferedInputStream(fis);
            buff= readBlock(bis);

            // dispose all the resources after using them.
            fis.close();
            bis.close();

            return buff;
    } catch (FileNotFoundException e) {
      e.printStackTrace();
      return null;
    } catch (IOException e) {
      e.printStackTrace();
      return null;
    }        
    }
    
    public static int b2int(byte b) {
        int k=(int)b & (int)0xFF;
        return k;
    }
    
    private int seek(byte what,byte[] source){
        for (int k=0;k<source.length;k++){
            if (source[k]==what){
                return k;
            }
        } 
        return -1;
    }
    
    public static boolean checkSig(byte[]source,int offset,byte[] sig){
        if (offset+sig.length<source.length){
            for (int i=0;i<sig.length;i++){
                if (sig[i]!=source[i+offset]) return false;
            }
            return true;
            
        }else {
            return false;
        }
    }
    
    protected boolean getImageSizeJPG(byte[] buff){
        byte b=0;
        byte[] ValidSig = {(byte)0xFF, (byte)0xD8};
        byte[] Parameterless = {(byte)0x01, (byte)0xD0, (byte)0xD1, (byte)0xD2, (byte)0xD3, (byte)0xD4, (byte)0xD5, (byte)0xD6, (byte)0xD7};
        //if ((buff[0]==ValidSig[0])&&(buff[1]==ValidSig[1])){
        if (checkSig(buff, 0, ValidSig)){
           
            for (int i=2;i<buff.length;i++){
                while (buff[i]==(byte)0xFF){
                    i=i+1;
                }
                b=buff[i];
                
                if ((b==(byte)0xC0)||(b==(byte)0xC1)) {
                    i=i+3;
                    int h=(b2int(buff[i+1]) <<8) +b2int(buff[i+2]);
                    int w=(b2int(buff[i+3]) <<8) +b2int(buff[i+4]);
                    width=w;
                    height=h;
                    return true;
                }else{
                    int p=0;
                    if((p=seek(b, Parameterless))==-1){
                        int g=(b2int(buff[i+1]) <<8) +b2int(buff[i+2]);
                        if (g>0){
                            i=i+g;
                        }

                    }
                }
            }
            return false;
        } else {
            return false;
        }
    }
    
    protected boolean getImageSizePNG(byte[] buff){
        byte b=0;
        byte[] ValidSig = {(byte)137, (byte)80, (byte)78, (byte)71, (byte)13, (byte)10, (byte)26, (byte)10};
        if (checkSig(buff, 0, ValidSig)){
            int i=0;
            i=18;
            int w=(b2int(buff[i]) <<8) +b2int(buff[i+1]);
            i=22;
            int h=(b2int(buff[i]) <<8) +b2int(buff[i+1]);
            width=w;
            height=h;
            return true;
        } else {
            return false;
        }
    }
    
    protected boolean getImageSize(byte[] buff,ImageType atype){
        switch (atype) {
            case JPG:
                return getImageSizeJPG(buff); 
            case PNG:                
                return getImageSizePNG(buff); 
            default:
                return false;
        }
    }
    
    /** Creates a new instance of JECImageInfo */
    public ImageInfo(String Filename) {        
        assignImage(null,Filename);        
    }

    public ImageInfo(BufferedInputStream stream,String Filename) {        
        assignImage(stream,Filename);        
    }
    
}
